<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram</title>
</head>
<body>
<canvas id="physicsCanvas" width="400" height="450"></canvas>
<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // --- Drawing Parameters ---
    const cx = 200;
    const cy = 100;
    const R_px = 50;
    const L_px = 150;
    const ceiling_y = 40;
    const ground_y = cy + L_px + L_px; // 100 + 150 + 150 = 400

    // --- Helper Functions ---

    /**
     * Draws a hatched surface (ceiling or ground).
     * @param {number} x1 - Start x-coordinate.
     * @param {number} y - y-coordinate of the surface line.
     * @param {number} x2 - End x-coordinate.
     * @param {number} hatch_dir - Direction of hatches (1 for down, -1 for up).
     * @param {number} hatch_len - Length of hatch marks.
     * @param {number} hatch_spacing - Spacing between hatch marks.
     */
    function drawHatchedSurface(x1, y, x2, hatch_dir, hatch_len = 10, hatch_spacing = 10) {
        ctx.save();
        ctx.lineWidth = 1;
        ctx.beginPath();
        ctx.moveTo(x1, y);
        ctx.lineTo(x2, y);
        ctx.stroke();

        ctx.beginPath();
        for (let x = x1; x <= x2; x += hatch_spacing) {
            ctx.moveTo(x, y);
            ctx.lineTo(x - hatch_len / Math.sqrt(2), y + hatch_dir * hatch_len / Math.sqrt(2));
        }
        ctx.stroke();
        ctx.restore();
    }

    /**
     * Draws an arrowhead at the end of a line.
     * @param {number} fromx - Start x of the line.
     * @param {number} fromy - Start y of the line.
     * @param {number} tox - End x of the line (where the head is).
     * @param {number} toy - End y of the line (where the head is).
     * @param {number} headlen - Length of the arrowhead sides.
     */
    function drawArrowhead(fromx, fromy, tox, toy, headlen = 8) {
        const angle = Math.atan2(toy - fromy, tox - fromx);
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
    }

    /**
     * Draws a spring using a visually similar pattern to the original image.
     * @param {number} x - The x-coordinate of the spring's central axis.
     * @param {number} y1 - The starting y-coordinate.
     * @param {number} y2 - The ending y-coordinate.
     * @param {number} coils - The number of coils.
     * @param {number} width - The width of the spring coils.
     */
    function drawSpring(x, y1, y2, coils = 7, width = 20) {
        ctx.beginPath();
        ctx.moveTo(x, y1);
        const h = y2 - y1;
        const lead = 5;
        ctx.lineTo(x, y1 + lead);
        const springBodyH = h - 2 * lead;
        const segmentH = springBodyH / coils;
        let currentY = y1 + lead;
        for (let i = 0; i < coils; i++) {
            ctx.quadraticCurveTo(x - width, currentY + segmentH / 2, x, currentY + segmentH);
            currentY += segmentH;
        }
        ctx.lineTo(x, y2);
        ctx.stroke();
    }

    // --- Main Drawing Logic ---
    ctx.lineWidth = 1.5;
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';

    // 1. Draw Ceiling and Ground
    drawHatchedSurface(50, ceiling_y, 350, 1);
    drawHatchedSurface(50, ground_y, 350, -1);

    // 2. Draw Pulley system
    // Suspension rod
    ctx.beginPath();
    ctx.moveTo(cx, ceiling_y);
    ctx.lineTo(cx, cy);
    ctx.stroke();
    // Pulley wheel
    ctx.beginPath();
    ctx.arc(cx, cy, R_px, 0, 2 * Math.PI);
    ctx.stroke();

    // 3. Draw Rope
    ctx.beginPath();
    const rope_left_x = cx - R_px;
    const rope_spring_y = cy + L_px;
    ctx.moveTo(rope_left_x, cy);
    ctx.lineTo(rope_left_x, rope_spring_y);
    ctx.arc(cx, cy, R_px, Math.PI, 0);
    const rope_right_x = cx + R_px;
    const rope_block_y = cy + L_px;
    ctx.lineTo(rope_right_x, rope_block_y);
    ctx.stroke();

    // 4. Draw Spring
    const spring_ground_y = rope_spring_y + L_px;
    drawSpring(rope_left_x, rope_spring_y, spring_ground_y, 7, 20);

    // 5. Draw Mass Block
    const block_size = 30;
    ctx.beginPath();
    ctx.rect(rope_right_x - block_size / 2, rope_block_y, block_size, block_size);
    ctx.stroke();

    // 6. Draw Labels and Annotations
    const italicFont = 'italic 21px "Times New Roman"';
    const normalFont = '21px "Times New Roman"';
    ctx.textAlign = 'left';
    ctx.textBaseline = 'middle';

    // Pulley labels
    ctx.font = italicFont;
    ctx.fillText('R', cx + 15, cy - 15);
    ctx.beginPath();
    ctx.moveTo(cx, cy);
    ctx.lineTo(cx + R_px, cy);
    drawArrowhead(cx, cy, cx + R_px, cy);
    ctx.stroke();
    
    const rLabelX = cx + R_px + 15;
    const rLabelY = cy + 5;
    ctx.font = italicFont;
    ctx.fillText('R = L/', rLabelX, rLabelY);
    const rPrefixWidth = ctx.measureText('R = L/').width;
    ctx.font = normalFont;
    ctx.fillText('π', rLabelX + rPrefixWidth, rLabelY);

    // Left side labels
    ctx.font = normalFont;
    ctx.fillText('λ', rope_left_x - 30, cy + L_px / 2 - 12);
    ctx.font = italicFont;
    ctx.fillText('L', rope_left_x - 30, cy + L_px / 2 + 15);
    
    const kLabelX = 20;
    const kLabelY = rope_spring_y + L_px / 2 - 10;
    ctx.font = italicFont;
    ctx.fillText('k = 5', kLabelX, kLabelY);
    let kPrefixWidth = ctx.measureText('k = 5').width;
    ctx.font = normalFont;
    ctx.fillText('λ', kLabelX + kPrefixWidth, kLabelY);
    const lambdaWidthK = ctx.measureText('λ').width;
    ctx.font = italicFont;
    ctx.fillText('g', kLabelX + kPrefixWidth + lambdaWidthK, kLabelY);
    
    ctx.font = italicFont;
    ctx.fillText('L', rope_left_x + 20, rope_spring_y + L_px / 2);

    // Right side labels
    ctx.font = normalFont;
    ctx.fillText('λ', rope_right_x + 15, cy + L_px / 2 - 12);
    ctx.font = italicFont;
    ctx.fillText('L', rope_right_x + 15, cy + L_px / 2 + 15);

    const mLabelX = rope_right_x + block_size;
    const mLabelY = rope_block_y + block_size / 2;
    ctx.font = italicFont;
    ctx.fillText('m = ', mLabelX, mLabelY);
    const mPrefixWidth = ctx.measureText('m = ').width;
    ctx.font = normalFont;
    ctx.fillText('λ', mLabelX + mPrefixWidth, mLabelY);
    const lambdaWidthM = ctx.measureText('λ').width;
    ctx.font = italicFont;
    ctx.fillText('L', mLabelX + mPrefixWidth + lambdaWidthM, mLabelY);

</script>
</body>
</html>